package org.dut.community.service;

import org.dut.community.dao.DiscussPostRepository;
import org.dut.community.entity.DiscussPost;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.CriteriaQueryBuilder;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightFieldParameters;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class ElasticsearchService {
    @Autowired
    private DiscussPostRepository discussRepository;
    @Autowired
    private ElasticsearchTemplate elasticTemplate;

    // 新增或修改
    public void saveDiscussPost(DiscussPost discussPost) {
        discussRepository.save(discussPost);
    }

    // 删除
    public void deleteDiscussPost(int id) {
        discussRepository.deleteById(id);
    }

    // 搜索
    public Page<DiscussPost> searchByTemplate(String keyword,int current,int limit) {
        // 搜索(Template)  --更完善
        // 查询标准构建，匹配字段"content"和"title"中包含"互联网寒冬"关键字的数据
        // 在这里使用matches，而不是contains，contains必须包含完整的关键字，而matches不需要，如果要匹配更多字段使用or或者and
        Criteria criteria = new Criteria("title").matches(keyword).or(new Criteria("content").matches(keyword));

        // 高亮前端格式：<em></em>
        List<HighlightField> highlightFieldList = new ArrayList<>();
        HighlightField highlightField = new HighlightField("title", HighlightFieldParameters.builder().withPreTags("<em>").withPostTags("</em>").build());
        highlightFieldList.add(highlightField);
        highlightField = new HighlightField("content", HighlightFieldParameters.builder().withPreTags("<em>").withPostTags("</em>").build());
        highlightFieldList.add(highlightField);
        Highlight highlight = new Highlight(highlightFieldList);
        HighlightQuery highlightQuery = new HighlightQuery(highlight, DiscussPost.class);

        // 构建细化查询
        CriteriaQueryBuilder builder = new CriteriaQueryBuilder(criteria)   // 指定关键词
                .withSort(Sort.by(Sort.Direction.DESC, "type"))  // 置顶
                .withSort(Sort.by(Sort.Direction.DESC, "score"))  // 热度
                .withSort(Sort.by(Sort.Direction.DESC, "createTime"))  // 时间
                .withHighlightQuery(highlightQuery)  // 指定关键词高亮格式
                .withPageable(PageRequest.of(current, limit));  //  按分页查询（第几页，显示几条数据）
        CriteriaQuery query = new CriteriaQuery(builder);

        // 通过elasticsearchTemplate查询
        SearchHits<DiscussPost> result = elasticTemplate.search(query, DiscussPost.class);  // 传入查询条件和实体类型

        // 处理结果
        List<SearchHit<DiscussPost>> searchHitList = result.getSearchHits();
        List<DiscussPost> discussPostList = new ArrayList<>();
        if(searchHitList != null){
            for (SearchHit<DiscussPost> hit : searchHitList) {
                // 遍历每个搜索命中对象
                DiscussPost post = hit.getContent();
                // 将高亮结果添加到返回的结果类中显示
                var titleHighlight = hit.getHighlightField("title");
                if (!titleHighlight.isEmpty()) {  // 如果标题中包含<em></em>
                    post.setTitle(titleHighlight.get(0)); // 那么就在内存中暂时修改格式，无Mapper不涉及数据库
                }
                var contentHighlight = hit.getHighlightField("content");
                if (!contentHighlight.isEmpty()) {
                    post.setContent(contentHighlight.get(0));
                }
                discussPostList.add(post);
            }
        }

        return new PageImpl<>(discussPostList, PageRequest.of(current, limit), result.getTotalHits());
    }


}
